#include "main.h"
#include "stm32f0xx_hal.h"
#include "userDht11.h"
#include "main.h"
#include "adc.h"
#include "tim.h"

//说明：经测试，dht11内部数据更新速度很慢，改变了温湿度环境，要等一会儿才能变化


uint8_t dht11valueCount=0;
uint8_t dth11valueBuf[50];
volatile int8_t dht11temZ,dht11temX,dht11DamZ,dht11DamX;   //分为整数和小数部分,温度和湿度
volatile int8_t dht11temZBackup,dht11temXBackup,dht11DamZBackup,dht11DamXBackup;   //作为备份数据，方便实时传输给外界，分为整数和小数部分
uint8_t userDht11State;

#define DHT11_START_STOP      0X00
#define DHT11_STATE_READY     0X01
#define DHT11_STATE_START     0X02
#define DHT11_STATE_DATA      0X03
#define DHT11_STATE_END       0X04
#define DHT11_STATE_DELAY     0X05
#define DHT11_STATE_ERROR     0X06

#define DHT11_DAT_HIGH()      HAL_GPIO_WritePin(DH11_DAT_GPIO_Port,DH11_DAT_Pin,GPIO_PIN_SET)   
#define DHT11_DAT_LOW()       HAL_GPIO_WritePin(DH11_DAT_GPIO_Port,DH11_DAT_Pin,GPIO_PIN_RESET)


uint8_t user_dht11DataDeal(void);

void user_dht11Init()
{
	userDht11State=DHT11_STATE_READY;
	dht11valueCount=0;
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
		if(htim==&htim3)
		{
			dth11valueBuf[dht11valueCount] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
			dht11valueCount++;
			if(dht11valueCount>=42)  //接收到的编码数量够了42个，关闭定时器，真正的数据前面还有应答信号产生的两个
			{
				HAL_TIM_IC_Stop_IT(htim,TIM_CHANNEL_1);
				if(user_dht11DataDeal()==0)  //获取到的数据有误
				{
						userDht11State=DHT11_STATE_ERROR;
				}
				else
				{
						userDht11State=DHT11_STATE_END;
				}
			}
	    __HAL_TIM_SET_COUNTER(&htim3,0);
		}
}

//把接收到的高低电平转换成温度湿度数据
uint8_t user_dht11DataDeal()
{
	uint8_t i;
	uint8_t check=0;
	//0位置上的数据可以抛弃
	if((dth11valueBuf[1]<150)&&(dth11valueBuf[1]>180))return 0;    //验证dht11应答信号长度
	
	
	dht11temZ=0;
	dht11temX=0;
	dht11DamZ=0;
	dht11DamX=0;
	check=0;
	//湿度整数部分
	for(i=0;i<8;i++)
	{
		if(dth11valueBuf[2+i]>100)
		{
			dht11DamZ|=(0x80>>i);
		}
	}
  //湿度小数部分目前dht11保留读出来都是0
	//湿度小数部分
	for(i=0;i<8;i++)
	{
		if(dth11valueBuf[10+i]>100)
		{
			dht11DamX|=(0x80>>i);
		}
	}		
	//温度整数部分
	for(i=0;i<8;i++)
	{
		if(dth11valueBuf[18+i]>100)
		{
			dht11temZ|=(0x80>>i);
		}
	}
	//温度小数部分，老版本AOSONG-DHT11读出来是0，新版本ASAIR-DHT11读出来有数据
	for(i=0;i<8;i++)
	{
		if(dth11valueBuf[26+i]>100)
		{
			dht11temX|=(0x80>>i);
		}
	}
	//校验和
	for(i=0;i<8;i++)
	{
		if(dth11valueBuf[34+i]>100)
		{
			check|=(0x80>>i);
		}
	}
	if(check==((dht11DamZ+dht11DamX+dht11temZ+dht11temX)&0x00ff))
	{
		return 1;
	}
	return 0;
}
void user_Dht11Scan()
{
	static uint8_t i;
	switch (userDht11State)
	{
		case DHT11_STATE_READY:
			DHT11_DAT_LOW();
			i=0;
			userDht11State=DHT11_STATE_START;
			break;
		case DHT11_STATE_START:
			i++;
			if(i>=2)            //拉低20ms之后拉高DAT引脚并打开定时器捕获功能
			{
				i=0;
				DHT11_DAT_HIGH();
				__HAL_TIM_SET_COUNTER(&htim3,0);
				HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
				userDht11State=DHT11_STATE_DATA;
			}
			break;
		case DHT11_STATE_DATA:
			i++;
			if(i>=2)  //超过20ms则认为超时
			{
				i=0;
				userDht11State=DHT11_STATE_ERROR;
			}
			break;
		case DHT11_STATE_END: //正确接收数据完成
			dht11temZBackup=dht11temZ;
			dht11DamZBackup=dht11DamZ;
		  dht11valueCount=0;
		  userDht11State=DHT11_STATE_DELAY;
			HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
			break;
		case DHT11_STATE_DELAY:
			i++;
			if(i>=200)   //2s间隔
			{
				i=0;
				userDht11State=DHT11_STATE_READY;
			}
			break;
		case DHT11_STATE_ERROR:
			HAL_TIM_IC_Stop_IT(&htim3,TIM_CHANNEL_1);
			__HAL_TIM_SET_COUNTER(&htim3,0);
			dht11valueCount=0;
			userDht11State=DHT11_STATE_DELAY;		
			break;
	}
}

//获取温湿度值
int8_t user_wenShidu(uint8_t ws)
{
	if(ws==DHT11_WENDU)
	{
		return dht11temZBackup;
	}
	else if(ws==DHT11_SHIDU)
	{
		return dht11DamZBackup;
	}
	return 0;
}

